﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Devices.PointOfService;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Storage.Streams;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace WellDone
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    /// 

    public sealed partial class MercuryDialog : Page
    {
        public event EventHandler CloseRequested;
        public ServiceReferenceOpenRPOS.Mercury mercuryRec;

        Popup dialogPopup;
        decimal purchase = 0, gratuity = 0;
        int invoice = 0, ordernumber = 0;
        MagneticStripeReader _reader = null;
        ClaimedMagneticStripeReader _claimedReader = null;
        public MercuryDialog()
        {
            this.InitializeComponent();
        }

        /// <summary>
        /// Creates the default magnetic stripe reader.
        /// </summary>
        /// <returns>true if magnetic stripe reader is created. Otherwise returns false</returns>
        private async Task<bool> CreateDefaultMagneticStripeReaderObject()
        {
            if (_reader == null)
            {
                _reader = await MagneticStripeReader.GetDefaultAsync();

                if (_reader == null)
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// Claim the magnetic stripe reader
        /// </summary>
        /// <returns>true if claim is successful. Otherwise returns false</returns>
        private async Task<bool> ClaimReader()
        {
            if (_claimedReader == null)
            {
                // claim the magnetic stripe reader
                _claimedReader = await _reader.ClaimReaderAsync();

                // enable the claimed magnetic stripe reader
                if (_claimedReader == null)
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// Enable the magnetic stripe reader.
        /// </summary>
        /// <returns>true if claim is successful. Otherwise returns false</returns>
        private async Task<bool> EnableReader()
        {

            await _claimedReader.EnableAsync();
            return true;
        }

        /// <summary>
        /// Event handler for the Release Device Requested event fired when magnetic stripe reader receives Claim request from another application
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"> Contains the ClaimedMagneticStripeReader that is sending this request</param>
        void OnReleaseDeviceRequested(object sender, ClaimedMagneticStripeReader args)
        {
            // let us retain the device always. If it is not retained, this exclusive claim will be lost.
            args.RetainDevice();
        }
        /// <summary>
        /// Event handler for the DataReceived event fired when a bank card is read by the magnetic stripe reader 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"> Contains the MagneticStripeReaderBankCardDataReceivedEventArgs which contains the data obtained in the scan</param>
        async void OnBankCardDataReceived(object sender, MagneticStripeReaderBankCardDataReceivedEventArgs args)
        {
            ServiceReferenceMercury.PaymentRequest request = new ServiceReferenceMercury.PaymentRequest();
            // read the data and display
            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                System.Diagnostics.Debug.WriteLine(getHexString(args.Report.Track2.EncryptedData));
                System.Diagnostics.Debug.WriteLine(getHexString(args.Report.AdditionalSecurityInformation));

                // Hide the "Cancel" button
                btnCancel.Visibility = Visibility.Collapsed;
                // Hide the "Manual" button
                btnManual.Visibility = Visibility.Collapsed;
                // Change message text to read "Authorizing..."
                tbMessage.Text = "Authorizing...";

                // Create a new Mercury request object
                request.EncryptedBlock = getHexString(args.Report.Track2.EncryptedData);
                request.EncryptedKey = getHexString(args.Report.AdditionalSecurityInformation);
                request.Purchase = purchase;
                request.Gratuity = gratuity;
                request.InvoiceNo = invoice;
                request.Authorize = purchase;
                request.EncryptedFormat = "MagneSafe";
                request.InvoiceNo = invoice;
                request.LaneID = 0;
                request.Memo = Globals.k_str_memo;
                request.OperatorID = Globals.currentLogin.col_UserName;
                request.RefNo = request.InvoiceNo.ToString();
                mercuryRec.bFilterFirstName = true;
                mercuryRec.bFilterLastName = true;
                mercuryRec.bFilterMiddleInitial = true;
                mercuryRec.bFilterAccountNumber = true;
                mercuryRec.bFilterExpDate = true;
                mercuryRec.bFilterOrderCheckID = true;
                mercuryRec.col_FirstName = args.FirstName;
                mercuryRec.col_LastName = args.Surname;
                mercuryRec.col_MiddleInitial = args.MiddleInitial;
                mercuryRec.col_AccountNumber = args.AccountNumber;
                mercuryRec.col_ExpDate = args.ExpirationDate;
                mercuryRec.col_OrderCheckID = invoice;
            });
            // Call the mercury web service for authorization...
            ServiceReferenceMercury.PaymentResponse response =
                await Globals.mercuryClient.ProcessPreAuthAsync(request);
            // Determine if the request got approved...
            System.Diagnostics.Debug.WriteLine(response.CmdStatus);
            if (response.CmdStatus == "Approved")
            {
                // Update the mercury record
                mercuryRec.bFilterAuthorized = true;
                mercuryRec.col_Authorized = true;
                mercuryRec.bFilterAccountNumber = true;
                mercuryRec.col_AccountNumber = response.AcctNo;
                mercuryRec.bFilterAuthCode = true;
                mercuryRec.col_AuthCode = response.AuthCode;
                mercuryRec.bFilterAcqRefData = true;
                mercuryRec.col_AcqRefData = response.AcqRefData;
                mercuryRec.bFilterRecordNumber = true;
                mercuryRec.col_RecordNumber = response.RecordNo;
                mercuryRec.bFilterProcessData = true;
                mercuryRec.col_ProcessData = response.ProcessData;
                mercuryRec.bFilterPosted = true;
                mercuryRec.col_Posted = false;
                await Globals.client.AddMercuryObjectAsync(Globals.token, mercuryRec);
                // Print the credit slip...
                ServiceReferenceOpenRPOS.PrintQueue pq = new ServiceReferenceOpenRPOS.PrintQueue();
                pq.bFilterCreditSlip = true;
                pq.col_CreditSlip = true;
                pq.bFilterOrderSummaryID = true;
                pq.col_OrderSummaryID = ordernumber;
                pq.bFilterPrinted = true;
                pq.col_Printed = false;
                pq.bFilterOrderCheckID = true;
                pq.col_OrderCheckID = invoice;
                pq.bFilterPrintRoute = true;
                var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
                Object value = localSettings.Values[Globals.k_str_settings_order_print_route];
                try
                {
                    pq.col_PrintRoute = Convert.ToByte(value);
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.Message);
                }
                try
                {
                    await Globals.client.AddPrintQueueObjectAsync(Globals.token, pq);
                    pq.bFilterPrintReceipt = true;
                    pq.col_PrintReceipt = true;
                    pq.col_CreditSlip = false;
                    await Globals.client.AddPrintQueueObjectAsync(Globals.token, pq);
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.Message);
                }
            }
            await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                () =>
                {
                    // Display the returned message...
                    tbMessage.Text = response.CmdStatus;
                    // Show the "Close" button
                    btnClose.Visibility = Visibility.Visible;
                }
                );
        }

        public string getHexString(IBuffer buffer)
        {
            byte[] rawBytes = new byte[(int)buffer.Length];
            using (var reader = DataReader.FromBuffer(buffer))
            {
                reader.ReadBytes(rawBytes);
            }
            return ByteArrayToString(rawBytes);
        }
        public static string ByteArrayToString(byte[] ba)
        {
            string hex = BitConverter.ToString(ba);
            return hex.Replace("-", "");
        }

        public async void init(decimal in_purchase, decimal in_gratuity, int in_invoice, int in_ordernumber)
        {
            purchase = in_purchase;
            gratuity = in_gratuity;
            invoice = in_invoice;
            ordernumber = in_ordernumber;
            if (await CreateDefaultMagneticStripeReaderObject())
            {
                if (_reader != null)
                {
                    // after successful creation, claim the reader for exclusive use and enable it so that data reveived events are received.
                    if (await ClaimReader())
                    {
                        if (_claimedReader != null)
                        {
                            // It is always a good idea to have a release device requested event handler. If this event is not handled, there is a chance that another app can 
                            // claim ownsership of the magnetic stripe reader.
                            _claimedReader.ReleaseDeviceRequested += OnReleaseDeviceRequested;

                            // after successfully claiming and enabling, attach the BankCardDataReceived event handler.
                            // Note: If the scanner is not enabled (i.e. EnableAsync not called), attaching the event handler will not be of any use because the API will not fire the event 
                            // if the claimedScanner has not beed Enabled
                            _claimedReader.BankCardDataReceived += OnBankCardDataReceived;

                            // Ask the API to decode the data by default. By setting this, API will decode the raw data from the magnetic stripe reader
                            _claimedReader.IsDecodeDataEnabled = true;

                            await EnableReader();
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Reset the Scenario state
        /// </summary>
        void ResetTheScenarioState()
        {
            if (_claimedReader != null)
            {
                // Detach the datareceived event handler and releasedevicerequested event handler
                _claimedReader.BankCardDataReceived -= OnBankCardDataReceived;
                _claimedReader.ReleaseDeviceRequested -= OnReleaseDeviceRequested;

                // release the Claimed Magnetic Stripe Reader and set to null
                _claimedReader.Dispose();
                _claimedReader = null;
            }

            if (_reader != null)
            {
                // release the Magnetic Stripe Reader and set to null
                _reader = null;
            }
        }
        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.CloseRequested != null)
            {
                this.CloseRequested(this, EventArgs.Empty);
                ResetTheScenarioState();
            }
        }
        private void ManualButton_Click(object sender, RoutedEventArgs e)
        {
            // Show the manual transaction dialog for Mercury...
            // Create a new "Manual Transaction" dialog
            MercuryHostedCheckoutDialog mhcd = new MercuryHostedCheckoutDialog();
            mhcd.CloseRequested += MercuryHostedCheckoutDialog_CloseRequested;
            mhcd.init();
            Page page = new Page();
            page = mhcd;
            // Create a new dialog popup
            page.Width = Windows.UI.Xaml.Window.Current.Bounds.Width;
            page.Height = Windows.UI.Xaml.Window.Current.Bounds.Height;
            dialogPopup = new Popup();
            dialogPopup.Child = page;
            dialogPopup.IsOpen = true;
        }

        private void CloseButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.CloseRequested != null)
            {
                this.CloseRequested(this, EventArgs.Empty);
                ResetTheScenarioState();
            }
        }

        private void MercuryHostedCheckoutDialog_CloseRequested(object sender, EventArgs e)
        {
            // Close the dialog...
            dialogPopup.IsOpen = false;
        }

        private void btnManual_Click(object sender, RoutedEventArgs e)
        {

        }
    }
}
